package com.linghang.wusthelper.util;


import libsvm.svm;
import libsvm.svm_model;
import libsvm.svm_node;


import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;


/**
 * @author origin
 * 教务处验证码识别工具类
 */
public class CodeIdentiUtil {


    /**
     * 验证码识别
     * @param uuid 图片存储id
     * @return 验证码
     */
    public static String CodeIdentification(String uuid){
        //todo  设置图片存储路径
        String dir = "./";

        BufferedImage image = CodeIdentiUtil.convert(dir+uuid+".png");
        List<BufferedImage> imageList = CodeIdentiUtil.cropImage(image);
        CodeIdentiUtil.getFeature(imageList,uuid);
        String code = getCode(dir+uuid+".txt");
        File file1 = new File(dir+uuid+".png");
        File file2 = new File(dir+uuid+".txt");
        if (file1.exists()){
            file1.delete();
        }
        if (file2.exists()){
            file2.delete();
        }
        return code;
    }

    /**
     * Libsvm预测
     * @param filepath 测试文件地址
     * @return
     */
    private static String getCode(String filepath){
        svm_model model = null;
        String code = "";
        try {
            //todo  替换Model文件地址
            model = svm.svm_load_model("model_file");
            BufferedReader reader = new BufferedReader(new FileReader(filepath));

            for (int i = 0; i< 4;i++) {
                String line = reader.readLine();
                StringTokenizer stringTokenizer = new StringTokenizer(line, " \t\n\n\f:");
                double target = Double.valueOf(stringTokenizer.nextToken());
                int m = stringTokenizer.countTokens() / 2;
                svm_node[] svm_nodes = new svm_node[m];
                for (int j = 0; j < m; j++) {
                    svm_nodes[j] = new svm_node();
                    svm_nodes[j].index = Integer.valueOf(stringTokenizer.nextToken());
                    svm_nodes[j].value = Double.valueOf(stringTokenizer.nextToken());
                }
                double x = svm.svm_predict(model, svm_nodes);
                code += (char)x;
            }
            reader.close();
            return code;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取单个字符的特征值
     * @param bufferedImages
     * @param uuid  特征值文件存储id
     */
    public static void getFeature(List<BufferedImage> bufferedImages,String uuid){
        //todo  设置文件存储路径
        String dir = "./";
        File file = new File(dir+uuid+".txt");
        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(file));

            for (BufferedImage tmp:bufferedImages){
                writer.write("0");
                int id = 0;
                int width = tmp.getWidth();
                int height = tmp.getHeight();
                for (int i = 0; i < height ;i++){
                    int pixCntX = 0;
                    for (int j = 0;j < width;j++){
                        if (tmp.getRGB(j,i) == -16777215){
                            pixCntX++;
                        }
                    }
                    writer.write(" " + id +":"+pixCntX);
                    id++;
                }

                for (int i = 0;i < width;i++){
                    int pixCntY = 0;
                    for (int j = 0;j < height;j++){
                        if (tmp.getRGB(i,j) == -16777215){
                            pixCntY++;
                        }
                    }
                    writer.write(" "+id+":"+pixCntY);
                    id++;
                }
//                writer.write("\n");
                writer.newLine();
            }
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 图像裁剪
     * @param image
     * @return
     */
    public static List<BufferedImage> cropImage(BufferedImage image){
        List<BufferedImage> bufferedImages = new ArrayList<>();
        for (int i = 0; i < 4;i++){
            int x = 4 + i*(9+1);
            int y = 4;
            bufferedImages.add(image.getSubimage(x,y,9,12));
        }
        return bufferedImages;
    }

    /**
     * 将图像转化成灰度图
     * @param filepath 图片地址
     * @return
     */
    public static BufferedImage convert(String filepath){
        BufferedImage image = null;
        File file = new File(filepath);
        try {
            image = ImageIO.read(file);
            int width = image.getWidth();
            int height = image.getHeight();
            for (int i = 0; i < height;i++){
                for (int j = 0;j < width;j++){
                    int p = image.getRGB(j,i);
//                    System.out.println(p);
                    //int a = (p >> 24) & 0xff;
                    int r = (p >> 16) & 0xff;
                    int g = (p >> 8) & 0xff;
                    int b = p & 0xff;
                    //int avg = (r + g + b) / 3;
                    //p = (a << 24) | (avg << 16) | (avg << 8) | avg;
                    int L = r * 299/1000 + g * 587/1000+ b * 114/1000;
                    //System.out.println(p);
                    //image.setRGB(j,i,p);
                    if (L<=110){
                        image.setRGB(j,i,-16777215);
                    }else {
                        image.setRGB(j,i,-1);
                    }
                }
            }
            return image;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}
